-module(mask).

-export([set_file/1,test/0,write/0]).

set_file(Module) ->
	put(module,Module),	
	ok.

write() ->
	write_erlang().

test() ->
	set_file(maskc_test),
	write_erlang().

write_erlang() ->
	case get(module) of
		module -> {error,no_module};
		Module -> 
			write_erlang(Module)
	end.

write_erlang(Module) ->
	Name = Module:get_name(),
	DataDes = Module:get_des(),
	create_file(Name,DataDes),
	ok.


create_num({MaskName,MaskNum}) -> 
	if
		MaskNum > 32 -> create_num({MaskName,MaskNum},"","",1);
		true -> {"\r\n\t`" ++ erlang:atom_to_list(MaskName) ++ "` int(11) NOT NULL DEFAULT '0',","," ++ erlang:atom_to_list(MaskName)}
	end.
create_num({MaskName,MaskNum},Sql,Record,Num) ->
	Sql1 = Sql ++ "\r\n\t`" ++ erlang:atom_to_list(MaskName) ++ "_" ++ erlang:integer_to_list(Num) ++ "` int(11) NOT NULL DEFAULT '0',",
	Record1 = Record ++ "," ++ erlang:atom_to_list(MaskName) ++ "_" ++ erlang:integer_to_list(Num),
	if
		MaskNum > 32 -> create_num({MaskName,MaskNum - 32},Sql1,Record1,Num + 1);
		true -> {Sql1,Record1}
	end.
create_file(Name,DataDes) ->
	Create = "mask_" ++ erlang:atom_to_list(Name),
	Sql = "DROP TABLE IF EXISTS `" ++ Create ++ "`;\r\nCREATE TABLE `" ++ Create ++ "` (\r\n\t`id` int(11) NOT NULL AUTO_INCREMENT,\r\n\t`pid` int(11) NOT NULL DEFAULT '0',",
	Record = "-record(" ++ Create ++ ",{id,pid",
	Fun = fun({MaskName,MaskNum},{Sql,Record}) ->
				  case create_num({MaskName,MaskNum}) of
					  {Sql1,Record1} -> {Sql ++ Sql1,Record ++ Record1};
					  _ -> {Sql,Record}
				  end
		  end,
	{Sql2,Record2} = lists:foldl(Fun, {Sql,Record}, DataDes),
	Sql3 = Sql2 ++ "\r\n\tPRIMARY KEY (`id`),\r\n\tUNIQUE KEY `usr` (`pid`)\r\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\r\n",
	Record3 = Record2 ++ "}).",
	
	case file:open(Create ++ ".erl", [write]) of
		{ok, File} ->
			file:write(File, "-module(" ++ Create ++ ").\r\n"),
			file:write(File, "-export([mask/3,check_mask/3,clear_mask/3,clear_mask/2,clear_mask/1]).\r\n"),
			file:write(File, "" ++ Record3 ++ "\r\n"),
			file:write(File, "\r\n"),
			file:write(File, "get_mask(Pid) -> lib_mask:get_mask(" ++ Create ++ ",Pid).\r\n"),
			file:write(File, "put_mask(Rec) -> lib_mask:put_mask(Rec).\r\n"),
			write_mask(Create,File,DataDes),	
			write_check_mask(Create,File,DataDes),
			write_clear_mask(Create,File,DataDes),
			write_clear_mask2(Create,File,DataDes),
			write_clear_mask3(Create,File,DataDes),
			file:write(File, "\r\n"),	
			file:close(File);		
		_ -> skip
	end,
	
	
	CreateSql = "sql_mask_" ++ erlang:atom_to_list(Name),
	case file:open(CreateSql ++ ".sql", [write]) of
		{ok, FileSql} ->
			file:write(FileSql, Sql3 ++ "\r\n"),
			file:close(FileSql);			
		_ -> skip
	end.

write_mask_num({MaskName,MaskNum},Record) -> 
	if
		MaskNum > 32 -> write_mask_num({MaskName,MaskNum},"",1,Record);
		true -> "mask(Pid," ++ erlang:atom_to_list(MaskName) ++ ",Index) when Index >= 1 andalso Index < " ++ erlang:integer_to_list(MaskNum + 1) ++ 
					" ->\r\n\t\tcase get_mask(Pid) of\r\n\t\t\tMask = #" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					" = Data} ->\r\n\t\t\t\tNewData = lib_mask:mask(Data,Index),\r\n\t\t\t\tput_mask(Mask#" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					" = NewData});\r\n\t\t\t_ -> skip\r\n\t\tend;\r\n"
	end.
write_mask_num({MaskName,MaskNum},Mask,Num,Record) ->
	if
		MaskNum > 32 -> 
			Mask1 = Mask ++ "mask(Pid," ++ erlang:atom_to_list(MaskName) ++ ",Index) when Index >= " ++ erlang:integer_to_list((Num - 1) * 32 + 1) ++ 
					" andalso Index < " ++ erlang:integer_to_list((Num - 1) * 32 + 33) ++ 
					" ->\r\n\t\tcase get_mask(Pid) of\r\n\t\t\tMask = #" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					"_" ++ erlang:integer_to_list(Num) ++ " = Data} ->\r\n\t\t\t\tNewData = lib_mask:mask(Data,Index - " ++ erlang:integer_to_list((Num - 1) * 32) ++
					"),\r\n\t\t\t\tput_mask(Mask#" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					"_" ++ erlang:integer_to_list(Num) ++ " = NewData});\r\n\t\t\t_ -> skip\r\n\t\tend;\r\n",
			write_mask_num({MaskName,MaskNum - 32},Mask1,Num + 1,Record);
		true -> 
			Mask1 = Mask ++ "mask(Pid," ++ erlang:atom_to_list(MaskName) ++ ",Index) when Index >= " ++ erlang:integer_to_list((Num - 1) * 32 + 1) ++ 
					" andalso Index < " ++ erlang:integer_to_list((Num - 1) * 32 + MaskNum + 1) ++ 
					" ->\r\n\t\tcase get_mask(Pid) of\r\n\t\t\tMask = #" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					"_" ++ erlang:integer_to_list(Num) ++ " = Data} ->\r\n\t\t\t\tNewData = lib_mask:mask(Data,Index - " ++ erlang:integer_to_list((Num - 1) * 32) ++
					"),\r\n\t\t\t\tput_mask(Mask#" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					"_" ++ erlang:integer_to_list(Num) ++ " = NewData});\r\n\t\t\t_ -> skip\r\n\t\tend;\r\n",
			Mask1
	end.
write_mask(Record,File,DataDes) ->
	Fun = fun({MaskName,MaskNum},Mask) ->
				  case write_mask_num({MaskName,MaskNum},Record) of
					  Mask1 when erlang:is_list(Mask1) -> Mask ++ Mask1;
					  _ -> Mask
				  end
		  end,
	MaskStr = lists:foldl(Fun, "", DataDes),
	file:write(File, MaskStr),
	file:write(File, "mask(_Pid,_Name,_Index) -> ok.\r\n").

write_check_mask_num({MaskName,MaskNum},Record) -> 
	if
		MaskNum > 32 -> write_check_mask_num({MaskName,MaskNum},"",1,Record);
		true -> "check_mask(Pid," ++ erlang:atom_to_list(MaskName) ++ ",Index) when Index >= 1 andalso Index < " ++ erlang:integer_to_list(MaskNum + 1) ++ 
					" ->\r\n\t\tcase get_mask(Pid) of\r\n\t\t\t#" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					" = Data} ->\r\n\t\t\t\tlib_mask:check_mask(Data,Index);\r\n\t\t\t_ -> skip\r\n\t\tend;\r\n"
	end.
write_check_mask_num({MaskName,MaskNum},Mask,Num,Record) ->
	if
		MaskNum > 32 -> 
			Mask1 = Mask ++ "check_mask(Pid," ++ erlang:atom_to_list(MaskName) ++ ",Index) when Index >= " ++ erlang:integer_to_list((Num - 1) * 32 + 1) ++ 
					" andalso Index < " ++ erlang:integer_to_list((Num - 1) * 32 + 33) ++ 
					" ->\r\n\t\tcase get_mask(Pid) of\r\n\t\t\t#" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					"_" ++ erlang:integer_to_list(Num) ++ " = Data} ->\r\n\t\t\t\tlib_mask:check_mask(Data,Index - " ++ erlang:integer_to_list((Num - 1) * 32) ++
					");\r\n\t\t\t_ -> false\r\n\t\tend;\r\n",
			write_check_mask_num({MaskName,MaskNum - 32},Mask1,Num + 1,Record);
		true -> 
			Mask1 = Mask ++ "check_mask(Pid," ++ erlang:atom_to_list(MaskName) ++ ",Index) when Index >= " ++ erlang:integer_to_list((Num - 1) * 32 + 1) ++ 
					" andalso Index < " ++ erlang:integer_to_list((Num - 1) * 32 + MaskNum + 1) ++ 
					" ->\r\n\t\tcase get_mask(Pid) of\r\n\t\t\t#" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					"_" ++ erlang:integer_to_list(Num) ++ " = Data} ->\r\n\t\t\t\tlib_mask:check_mask(Data,Index - " ++ erlang:integer_to_list((Num - 1) * 32) ++
					");\r\n\t\t\t_ -> false\r\n\t\tend;\r\n",
			Mask1
	end.
write_check_mask(Record,File,DataDes) ->
	Fun = fun({MaskName,MaskNum},Mask) ->
				  case write_check_mask_num({MaskName,MaskNum},Record) of
					  Mask1 when erlang:is_list(Mask1) -> Mask ++ Mask1;
					  _ -> Mask
				  end
		  end,
	MaskStr = lists:foldl(Fun, "", DataDes),
	file:write(File, MaskStr),
	file:write(File, "check_mask(_Pid,_Name,_Index) -> false.\r\n").

write_clear_mask_num({MaskName,MaskNum},Record) -> 
	if
		MaskNum > 32 -> write_clear_mask_num({MaskName,MaskNum},"",1,Record);
		true -> "clear_mask(Pid," ++ erlang:atom_to_list(MaskName) ++ ",Index) when Index >= 1 andalso Index < " ++ erlang:integer_to_list(MaskNum + 1) ++ 
					" ->\r\n\t\tcase get_mask(Pid) of\r\n\t\t\tMask = #" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					" = Data} ->\r\n\t\t\t\tNewData = lib_mask:clear_mask(Data,Index),\r\n\t\t\t\tput_mask(Mask#" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					" = NewData});\r\n\t\t\t_ -> skip\r\n\t\tend;\r\n"
	end.
write_clear_mask_num({MaskName,MaskNum},Mask,Num,Record) ->
	if
		MaskNum > 32 -> 
			Mask1 = Mask ++ "clear_mask(Pid," ++ erlang:atom_to_list(MaskName) ++ ",Index) when Index >= " ++ erlang:integer_to_list((Num - 1) * 32 + 1) ++ 
					" andalso Index < " ++ erlang:integer_to_list((Num - 1) * 32 + 33) ++ 
					" ->\r\n\t\tcase get_mask(Pid) of\r\n\t\t\tMask = #" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					"_" ++ erlang:integer_to_list(Num) ++ " = Data} ->\r\n\t\t\t\tNewData = lib_mask:clear_mask(Data,Index - " ++ erlang:integer_to_list((Num - 1) * 32) ++
					"),\r\n\t\t\t\tput_mask(Mask#" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					"_" ++ erlang:integer_to_list(Num) ++ " = NewData});\r\n\t\t\t_ -> skip\r\n\t\tend;\r\n",
			write_clear_mask_num({MaskName,MaskNum - 32},Mask1,Num + 1,Record);
		true -> 
			Mask1 = Mask ++ "clear_mask(Pid," ++ erlang:atom_to_list(MaskName) ++ ",Index) when Index >= " ++ erlang:integer_to_list((Num - 1) * 32 + 1) ++ 
					" andalso Index < " ++ erlang:integer_to_list((Num - 1) * 32 + MaskNum + 1) ++ 
					" ->\r\n\t\tcase get_mask(Pid) of\r\n\t\t\tMask = #" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					"_" ++ erlang:integer_to_list(Num) ++ " = Data} ->\r\n\t\t\t\tNewData = lib_mask:clear_mask(Data,Index - " ++ erlang:integer_to_list((Num - 1) * 32) ++
					"),\r\n\t\t\t\tput_mask(Mask#" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ 
					"_" ++ erlang:integer_to_list(Num) ++ " = NewData});\r\n\t\t\t_ -> skip\r\n\t\tend;\r\n",
			Mask1
	end.
write_clear_mask(Record,File,DataDes) ->
	Fun = fun({MaskName,MaskNum},Mask) ->
				  case write_clear_mask_num({MaskName,MaskNum},Record) of
					  Mask1 when erlang:is_list(Mask1) -> Mask ++ Mask1;
					  _ -> Mask
				  end
		  end,
	MaskStr = lists:foldl(Fun, "", DataDes),
	file:write(File, MaskStr),
	file:write(File, "clear_mask(_Pid,_Name,_Index) -> ok.\r\n").

write_clear_mask_num2({MaskName,MaskNum},Record) -> 
	if
		MaskNum > 32 ->
			MaskStr = write_clear_mask_num2({MaskName,MaskNum},"",1),
			MaskStr1 = string:sub_string(MaskStr, 2),
			"clear_mask(Pid," ++ erlang:atom_to_list(MaskName) ++ ") ->\r\n\tcase get_mask(Pid) of\r\n\t\tMask = #" ++ Record ++ "{} ->\r\n\t\t\tput_mask(Mask#" ++ Record ++ "{" ++ MaskStr1 ++ "});\r\n\t\t_ -> ok\r\n\tend;\r\n";			
		true -> "clear_mask(Pid," ++ erlang:atom_to_list(MaskName) ++ ") ->\r\n\tcase get_mask(Pid) of\r\n\t\tMask = #" ++ Record ++ "{} ->\r\n\t\t\tput_mask(Mask#" ++ Record ++ "{" ++ erlang:atom_to_list(MaskName) ++ " = 0});\r\n\t\t_ -> ok\r\n\tend;\r\n"
	end.
write_clear_mask_num2({MaskName,MaskNum},Mask,Num) ->
	Mask1 = Mask ++ "," ++ erlang:atom_to_list(MaskName) ++ "_" ++ erlang:integer_to_list(Num) ++ " = 0",
	if
		MaskNum > 32 ->
			write_clear_mask_num3({MaskName,MaskNum - 32},Mask1,Num + 1);
		true -> 
			Mask1
	end.
write_clear_mask2(Record,File,DataDes) ->
	Fun = fun({MaskName,MaskNum},Mask) ->
				  case write_clear_mask_num2({MaskName,MaskNum},Record) of
					  Mask1 when erlang:is_list(Mask1) -> Mask ++ Mask1;
					  _ -> Mask
				  end
		  end,
	MaskStr = lists:foldl(Fun, "", DataDes),
	file:write(File, MaskStr),
	file:write(File, "clear_mask(_Pid,_Name) -> ok.\r\n").

write_clear_mask_num3({MaskName,MaskNum}) -> 
	if
		MaskNum > 32 -> write_clear_mask_num3({MaskName,MaskNum},"",1);
		true -> "," ++ erlang:atom_to_list(MaskName) ++ " = 0"
	end.
write_clear_mask_num3({MaskName,MaskNum},Mask,Num) ->
	Mask1 = Mask ++ "," ++ erlang:atom_to_list(MaskName) ++ "_" ++ erlang:integer_to_list(Num) ++ " = 0",
	if
		MaskNum > 32 ->
			write_clear_mask_num3({MaskName,MaskNum - 32},Mask1,Num + 1);
		true -> 
			Mask1
	end.
write_clear_mask3(Record,File,DataDes) ->
	Fun = fun({MaskName,MaskNum},Mask) ->
				  case write_clear_mask_num3({MaskName,MaskNum}) of
					  Mask1 when erlang:is_list(Mask1) -> Mask ++ Mask1;
					  _ -> Mask
				  end
		  end,
	MaskStr = lists:foldl(Fun, "", DataDes),
	MaskStr1 = string:sub_string(MaskStr, 2),
	file:write(File, "clear_mask(Pid) ->\r\n\tcase get_mask(Pid) of\r\n\t\tMask = #" ++ Record ++ "{} -> put_mask(Mask#" ++ Record ++ "{" ++ MaskStr1 ++ "});\r\n\t_ -> ok\r\n\tend.\r\n").